﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using ImageHandler;
using MvcPaging;
using Stamp_For_Africa_Version_2.Helpers;
using Stamp_For_Africa_Version_2.Models;
using System.Web.Mvc;

namespace Stamp_For_Africa_Version_2.Repositories
{
  public class StampRepository
  {
    private StampsDataContext db = new StampsDataContext();
    //
    // Query Methods

    public IQueryable<Stamp> FindAllStamps(Guid userId)
    {
        return db.Stamps;
    }

		public IQueryable<Stamp> FindAllStampsByCountryName(String country)
		{
			return db.Stamps.Where(u => u.Country.Name.ToLower().Contains(country) ||
			                            u.Country.Abbreviation.ToLower().Contains(country));
		}
		public IQueryable<Stamp> FindAllStampsByDisplayName(String displayName)
		{
			return db.Stamps.Where(u => u.DisplayName.ToLower().Contains(displayName));
		}
		public IQueryable<Stamp> FindAllStampsByCategoryName(String categoryName)
		{
			return db.Stamps.Where(u => u.Category.DisplayName.ToLower().Contains(categoryName));
		}
		public IQueryable<Stamp> FindAllStampsByArtistName(String artistName)
		{
			return
				db.Stamps.Where(
					u =>
					u.Artist.Name.ToLower().Contains(artistName) || u.Artist.Surname.ToLower().Contains(artistName) ||
					u.Artist.DisplayName.ToLower().Contains(artistName));
		}


    public IQueryable<Stamp> FindAllStamps(StampFilter[] filters)
    {
      //Filter code comes here
      return db.Stamps;

    }

    public IPageOfList<Stamp> SelectRange(int pageIndex, int pageSize, Guid userId)
    {
      IPageOfList<Stamp> range = db.Stamps.ToPageOfList(pageIndex, pageSize);
      if (userId != Guid.Empty)
      {
				List<Guid> userStamps = db.Collections.Where(u => u.UserId == userId).Select(u => u.StampId).ToList();
        foreach (var stamp in range)
        {
          if (userStamps.Contains(stamp.Id))
            stamp.InMyCollection = true;
        }
      }

      return range;
    }   

		public IPageOfList<Stamp> SelectRange(int pageIndex, int pageSize, String countryId, String categoryId, String issuedFrom, Guid userId, String stampTypeId, String artistId)
    {
			IPageOfList<Stamp> range = db.Stamps.Where(
					u =>
					u.CategoryId.ToString().Contains(categoryId) && u.CountryId.ToString().Contains(countryId) && u.TypeId.ToString().Contains(stampTypeId) && u.ArtistId.ToString().Contains(artistId)).
					ToPageOfList(pageIndex, pageSize);

      if (userId != Guid.Empty)
      {
				List<Guid> userStamps = db.Collections.Where(u => u.UserId == userId).Select(u => u.StampId).ToList();
        foreach (var stamp in range)
        {
          if (userStamps.Contains(stamp.Id))
            stamp.InMyCollection = true;
        }
      }
      

      return range;
		}



		public IPageOfList<Stamp> SearchRange(int pageIndex, int pageSize, String searchString, String countryId, String categoryId, String issuedFrom, Guid userId)
		{
			return new PageOfList<Stamp>(null, 0, 0, 0);
		}

		

		public List<String> GetAllYears()
		{
			List<int> dates = db.Stamps.Select(u => u.FromDate).Distinct().ToList();

			List<String> returnDates = new List<string>();
			foreach (var dateTime in dates)
			{
				returnDates.Add(dateTime.ToString());
			}

			return returnDates;
		}

    public List<Stamp> FindAllStamps(MatchResults results)
    {
      //IEnumerable<Guid> stampIds = results.Results.Select(u => u.MatchedDBStampId);
			
			if (results == null)
				return new List<Stamp>();

      List<Stamp> returnList = new List<Stamp>();
      foreach (var imageMatch in results.Results)
      {
        Stamp stamp = db.Stamps.Where(u => u.Id == imageMatch.MatchedDBStampId).SingleOrDefault();
        if (stamp != null)
          stamp.MatchProbability = imageMatch.PctOfMatch;
        returnList.Add( stamp );
      }
      return returnList;

      //return db.Stamps.Where(u => stampIds.Contains(u.Id));
    }

		public IQueryable<Stamp> FindAllStamps(String countryId, String artistId, String currencyId, String categoryId )
		{
			return db.Stamps.Where(x => x.CountryId.ToString().Contains(countryId)
			                            && x.ArtistId.ToString().Contains(artistId)
			                            && x.CurrencyId.ToString().Contains(currencyId) 
                                  && x.CategoryId.ToString().Contains(categoryId));
		}

		public Stamp GetStamp(Guid id, Guid userId)
    {

			Stamp stamp = db.Stamps.SingleOrDefault(d => d.Id == id);

			if ((userId != Guid.Empty) && (stamp != null))
			{
				CollectionRepository collectionRepository = new CollectionRepository();
				//Retrieve mint never hindged count
				stamp.MintNeverHingedCount = collectionRepository.GetStampCount(userId, stamp.Id, 0);
				stamp.MintHingedCount = collectionRepository.GetStampCount(userId, stamp.Id, 1);
				stamp.UsedCount = collectionRepository.GetStampCount(userId, stamp.Id, 2);
			}

    	return stamp;
    }

		public List<Variation> GetStampVariations(Guid stampId)
		{
			return db.Variations.Where(u => u.StampId == stampId).ToList();
		}
		public void AddStampVariation(Variation variation)
		{
			db.Variations.InsertOnSubmit(variation);
			Save();
		}
		public void RemoveStampVariation(Guid variationId)
		{
			Variation variation = db.Variations.Where(u => u.Id == variationId).SingleOrDefault();
			if (variation != null)
			{
				db.Variations.DeleteOnSubmit(variation);
				Save();
			}
		}

    public void LinkStamptoStamp(Guid parentId, Guid childId, LinkType linkType)
    {
      StampLink stampLink = new StampLink();
      stampLink.ChildStampId = childId;
      stampLink.ParentStampId = parentId;
      stampLink.LinkType = linkType;
      stampLink.Id = Guid.NewGuid();
      db.StampLinks.InsertOnSubmit(stampLink);
      db.SubmitChanges();
    }
		
		public void RemoveStampLink(Guid parentId, Guid childId)
		{
			StampLink stampLink =
				db.StampLinks.Where(u => u.ParentStampId == parentId && u.ChildStampId == childId).SingleOrDefault();
			if (stampLink != null)
			{
				db.StampLinks.DeleteOnSubmit(stampLink);
				Save();
			}
		}

    //
    // Insert/Delete Methods

    public void Add(Stamp stamp)
    {
    	stamp.DateAdded = DateTime.Now;
      db.Stamps.InsertOnSubmit(stamp);
    }

    public void Delete(Stamp stamp)
    {
			db.Stamps.DeleteOnSubmit(stamp);
      db.StampFeatures.DeleteOnSubmit(stamp.StampFeature);
			db.SubmitChanges();			
      
    }

    public Guid GetLinkedStamp(Guid parentId, LinkType linkType)
    {
      if (db.StampLinks.Where(u => u.ParentStampId == parentId && u.LinkType == linkType).Count() > 0)
      {
        return db.StampLinks.Where(u => u.ParentStampId == parentId && u.LinkType == linkType).SingleOrDefault().ChildStampId;
      }

      return Guid.Empty;
    }

		public List<Stamp> GetLinkedStamps(Guid parentId, LinkType linkType)
		{

			List<StampLink> stampLinks = db.StampLinks.Where(u => u.ParentStampId == parentId && u.LinkType == linkType).ToList();
			return db.Stamps.Where(u => stampLinks.Select(x => x.ChildStampId).Contains(u.Id)).ToList();

		}

		public bool IsAStampVariant(Guid stampId)
		{
			if (db.StampLinks.Where(u => u.ChildStampId == stampId && u.LinkType == LinkType.Variation).Count() > 0)
				return true;
			return false;

		}
		public Stamp GetParentStampOfVariant(Guid stampId)
		{
			StampLink stampLink = db.StampLinks.Where(u => u.ChildStampId == stampId && u.LinkType == LinkType.Variation).SingleOrDefault();
			return db.Stamps.Where(u => u.Id == stampLink.ParentStampId).SingleOrDefault();
		}
    //
    // Persistence

    public void Save()
    {
      db.SubmitChanges();
    }
  }
}